package io.github.harmonly.skyblock.util;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.regex.Pattern;

public class Replacer {

    private static final Map<String, Pattern> PATTERN_CACHE = new ConcurrentHashMap<>();

    private static final Function<String, Pattern> PATTERN_CREATOR = p -> Pattern.compile(p, Pattern.LITERAL);

    public static String replaceIn(String content, Object... replacements) {
        return Replacer.builder().content(content).replace(replacements);
    }

    public static String replaceIn(String content, Map<?, ?> replacements) {
        return Replacer.builder().content(content).replace(replacements);
    }

    public static Replacer builder() {
        return new Replacer();
    }

    private String content;

    private String prefix = "%%";

    private String suffix = "%%";

    public Replacer placeholder(String prefix, String suffix) {
        this.prefix = prefix;
        this.suffix = suffix;
        return this;
    }

    public Replacer content(String content) {
        this.content = content;
        return this;
    }

    public Replacer prefix(String prefix) {
        this.prefix = prefix;
        return this;
    }

    public Replacer suffix(String suffix) {
        this.suffix = suffix;
        return this;
    }

    public String replace(Object... replacements) {
        Map<String, String> map = new LinkedHashMap<>();
        for (int i = 1; i < replacements.length; i += 2) {
            map.put(replacements[i - 1].toString(), replacements[i].toString());
        }
        return replace(map);
    }

    public String replace(Map<?, ?> replacements) {
        for (Map.Entry<?, ?> entry : replacements.entrySet()) {
            String value = entry.getValue() == null ? "" : entry.getValue().toString();
            String placeholder = prefix + entry.getKey() + suffix;
            content = PATTERN_CACHE.computeIfAbsent(placeholder, PATTERN_CREATOR)
                    .matcher(content).replaceAll(value);
        }
        return content;
    }
}
